package com.sen.rbac.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.sen.common.common.enums.CommonEnum;
import com.sen.common.common.exception.RecordNotFoundException;
import com.sen.common.common.response.PageVo;
import com.sen.common.common.util.SnowflakeIdWorker;
import com.sen.common.redis.bean.RedisBean;
import com.sen.common.tenant.config.TenantContextHolder;
import com.sen.common.user.config.UserContextHolder;
import com.sen.rbac.constant.RbacConstant;
import com.sen.rbac.dto.SysTenantEntityTypeDTO;
import com.sen.rbac.exception.RbacException;
import com.sen.rbac.mapper.SysAccountDao;
import com.sen.rbac.mapper.SysRoleAccountDao;
import com.sen.rbac.mapper.SysRoleDao;
import com.sen.rbac.mapper.SysTenantEntityTypeDao;
import com.sen.rbac.model.SysAccount;
import com.sen.rbac.model.SysRole;
import com.sen.rbac.model.SysRoleAccount;
import com.sen.rbac.model.SysTenantEntityType;
import com.sen.rbac.service.SysRoleAccountService;
import com.sen.rbac.service.TenantEntityTypeService;
import com.sen.rbac.vo.SysTenantEntityTypeVO;
import lombok.extern.slf4j.Slf4j;
import org.modelmapper.ModelMapper;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

import static com.sen.common.common.response.ResultMsgEnum.RECORD_NOT_EXIST;
import static com.sen.rbac.enums.RbacMsgEnum.ACCOUNT_NOT_EXIST;
import static com.sen.rbac.enums.RbacMsgEnum.object_exist;

/**
 * @author esjiang
 */
@Service
@Slf4j
public class TenantEntityTypeServiceImpl extends ServiceImpl<SysTenantEntityTypeDao, SysTenantEntityType> implements TenantEntityTypeService {

    @Resource
    ModelMapper modelMapper ;

    @Resource
    SysRoleDao sysRoleDao ;

    @Resource
    RedisBean redisBean ;

    @Resource
    SysAccountDao sysAccountDao ;

    @Resource
    SysRoleAccountDao sysRoleAccountDao ;

    @Resource
    SysRoleAccountService sysRoleAccountService ;

    @Resource
    SysTenantEntityTypeDao sysTenantEntityTypeDao ;

    static final String field_code = "roleGroupCode" ;

    static final String base_key = "base:" ;

    @Override
    public PageVo<SysTenantEntityTypeVO> list(SysTenantEntityTypeDTO sysTenantEntityTypeDTO) {
        LambdaQueryWrapper<SysTenantEntityType> queryWrapper = Wrappers.<SysTenantEntityType>lambdaQuery()
                .eq(StrUtil.isNotBlank(sysTenantEntityTypeDTO.getEntityType()), SysTenantEntityType::getEntityType, sysTenantEntityTypeDTO.getEntityType())
                .eq(StrUtil.isNotBlank(sysTenantEntityTypeDTO.getEnable()), SysTenantEntityType::getEnable, sysTenantEntityTypeDTO.getEnable())
                .eq(StrUtil.isNotBlank(sysTenantEntityTypeDTO.getSystemCode()), SysTenantEntityType::getSystemCode, sysTenantEntityTypeDTO.getSystemCode());
        /** 平台管理员可以查看所有得主体类型 */
        if (UserContextHolder.isSuperAdmin()){
            queryWrapper.like(StrUtil.isNotBlank(sysTenantEntityTypeDTO.getTenantCode()),SysTenantEntityType::getTenantCode,sysTenantEntityTypeDTO.getTenantCode()) ;
        }else {
            /** 运营专员只能查看自己得主体类型 */
            queryWrapper.eq(SysTenantEntityType::getTenantCode, TenantContextHolder.getTenant());
        }
        Page<SysTenantEntityType> page = page(new Page<>(sysTenantEntityTypeDTO.getPage(), sysTenantEntityTypeDTO.getPageSize()), queryWrapper);
       return PageVo.<SysTenantEntityTypeVO>builder()
                .list(page.getRecords().stream().map(record->modelMapper.map(record,SysTenantEntityTypeVO.class)).collect(Collectors.toList()))
                .total(page.getTotal())
                .build();
    }

    @Transactional(rollbackFor = RuntimeException.class)
    @Override
    public void saveOrUpdate(SysTenantEntityTypeDTO sysTenantEntityTypeDTO) {
        if (StrUtil.isBlank(sysTenantEntityTypeDTO.getEntityTypeCode())){
            sysTenantEntityTypeDTO.setEntityTypeCode(SnowflakeIdWorker.generateStrId());
        }
        /** 判断是否需要增加角色 ,主体类型编码=角色编码*/
        String tenantCode = sysTenantEntityTypeDTO.getTenantCode();
        String systemCode = sysTenantEntityTypeDTO.getSystemCode();
        String entityType = sysTenantEntityTypeDTO.getEntityType();
        List<SysTenantEntityType> list = list(Wrappers.<SysTenantEntityType>lambdaQuery()
                .eq(SysTenantEntityType::getTenantCode, tenantCode)
                .eq(SysTenantEntityType::getSystemCode, systemCode)
                .eq(SysTenantEntityType::getEntityType,entityType)
        );
        if (CollUtil.isNotEmpty(list)){
            throw new RbacException(object_exist) ;
        }
        saveOrUpdate(modelMapper.map(sysTenantEntityTypeDTO,SysTenantEntityType.class)) ;
        String roleCode = sysTenantEntityTypeDTO.getEntityTypeCode();
        sysRoleDao.insert(SysRole.builder()
                .code(roleCode)
                .name(Convert.toStr(redisBean.getHashValues(base_key +field_code,sysTenantEntityTypeDTO.getEntityType())))
                .tenantCode(sysTenantEntityTypeDTO.getTenantCode())
                .groupCode(sysTenantEntityTypeDTO.getEntityType())
                .entityCode(UserContextHolder.getPeople().getEntityCode())
                .build()) ;
        /** 同步权限 **/
        syncEntityTypeRoles(roleCode);
    }

    @Transactional(rollbackFor = RuntimeException.class)
    @Override
    public void del(String id) {
        SysTenantEntityType sysTenantEntityType = getById(id) ;
        if (ObjectUtil.isNull(sysTenantEntityType)){
            throw new RecordNotFoundException(RECORD_NOT_EXIST) ;
        }
        sysTenantEntityType.setEnable(CommonEnum.ENABLE_NO.getCode());
        saveOrUpdate(sysTenantEntityType) ;
        /** 是否需要回收权限，暂不回收 **/
    }

    @Transactional(rollbackFor = RuntimeException.class)
    @Override
    public void syncEntityTypeRoles(String entityTypeCode){
        SysTenantEntityType sysTenantEntityType = getOne(Wrappers.<SysTenantEntityType>lambdaQuery().eq(SysTenantEntityType::getEntityTypeCode, entityTypeCode));
        if (ObjectUtil.isNull(sysTenantEntityType)){
            log.warn("同步主体类型:{}权限到主体",entityTypeCode);
        }
        /** 查找主体的管理员，并查询出绑定的角色信息，是否存在entityType类型的角色  **/
        List<SysRoleAccount> sysRoleAccounts = new ArrayList<>();
        List<String> needAddEntityTypeUserName = sysTenantEntityTypeDao.findNeedAddEntityTypeUserName(RbacConstant.user_type_3, sysTenantEntityType.getEntityType());
        if (CollUtil.isNotEmpty(needAddEntityTypeUserName)){
            for (int i = 0; i < needAddEntityTypeUserName.size(); i++) {
                sysRoleAccounts.add(SysRoleAccount.builder()
                        .roleCode(sysTenantEntityType.getEntityTypeCode())
                        .userName(needAddEntityTypeUserName.get(i))
                        .build());
            }
            sysRoleAccountService.saveBatch(sysRoleAccounts) ;
        }
    }

    @Transactional(rollbackFor = RuntimeException.class)
    @Override
    public void syncEntityTypeRoles(String entityCode,String entityTypeCodes){
        /** 1，先查询saas全部的主体类型 **/
        List<SysTenantEntityType> sysTenantEntityTypes = list(Wrappers.<SysTenantEntityType>lambdaQuery()
         .select(SysTenantEntityType::getEntityType, SysTenantEntityType::getEntityTypeCode)
         .eq(SysTenantEntityType::getEnable,CommonEnum.ENABLE_YES.getCode())
         .in(SysTenantEntityType::getEntityType, StrUtil.split(entityTypeCodes,","))
         );
         /** 2，查询当前主体的管理员的角色code **/
        /** 找到主体的管理员 **/
        SysAccount sysAccount = sysAccountDao.selectOne(Wrappers.<SysAccount>lambdaQuery().select(SysAccount::getUserName)
                .eq(SysAccount::getEntityCode, entityCode)
                .eq(SysAccount::getUserType, RbacConstant.user_type_3)
                .eq(SysAccount::getEnable,CommonEnum.ENABLE_YES.getCode())
                .eq(SysAccount::getDelFlag,CommonEnum.DEL_NO.getCode())
                .eq(SysAccount::getLocked,CommonEnum.LOCK_NO.getCode())
        );
        if (ObjectUtil.isNull(sysAccount)){
            throw new RbacException(ACCOUNT_NOT_EXIST) ;
        }
        /** 查询主体管理员绑定的角色 **/
        List<SysRoleAccount> sysRoleAccounts = sysRoleAccountDao.selectList(Wrappers.<SysRoleAccount>lambdaQuery().select(SysRoleAccount::getRoleCode)
                .eq(SysRoleAccount::getUserName,sysAccount.getUserName())
        );
        List<String> ownRoles = CollUtil.newArrayList() ;
        if (CollUtil.isNotEmpty(sysRoleAccounts)){
            ownRoles = sysRoleAccounts.stream().map(sysRoleAccount -> sysRoleAccount.getRoleCode()).collect(Collectors.toList());
        }
        final List<String> finalOwnRoles = ownRoles;
        List<SysRoleAccount> newRoleAccounts = new ArrayList<>();
        sysTenantEntityTypes.stream().filter(sysTenantEntityType -> !finalOwnRoles.contains(sysTenantEntityType.getEntityTypeCode()))
                .map(sysTenantEntityType -> {
                    SysRoleAccount sysRoleAccount = SysRoleAccount.builder()
                            .roleCode(sysTenantEntityType.getEntityTypeCode())
                            .userName(sysAccount.getUserName())
                            .build();
                    newRoleAccounts.add(sysRoleAccount) ;
                    return sysTenantEntityType ;
                }).collect(Collectors.toList());
        sysRoleAccountService.saveBatch(newRoleAccounts) ;
        return ;
    }
}
